/// <reference name="MicrosoftAjax.debug.js" />
/// <reference path="../../Resources/js/jquery/jquery.debug.js" />
/// <reference path="Constraint.js" />

Type.registerNamespace("BM");

// IdentityConstraint object

BM.IdentityConstraint = function(item, data) {
    BM.IdentityConstraint.initializeBase(this, [item, data]);
    this.behavior = $create(BM.IdentityConstraintBehavior, { "Root": this, "id": this.getBehaviorId() }, null, null, this.item.getNode());
}

BM.IdentityConstraint.prototype = {

    getName: function() {
        return this.getProperty('name');
    },

    getBehaviorId: function() {
        return this.item.getId() + '_' + this.getName();
    },

    isMet: function() {
        return true;
    }
}

BM.IdentityConstraint.registerClass("BM.IdentityConstraint", BM.Constraint);

// IdentityConstraintBehavior

BM.IdentityConstraintBehavior = function(element) {
    BM.IdentityConstraintBehavior.initializeBase(this, [element]);
    this.root = null;
    this.keyReferences = new Array();
    this.keys = new Array();
}

BM.IdentityConstraintBehavior.prototype = {
    get_Root: function () {
        return this.root;
    },

    set_Root: function (value) {
        this.root = value;
    },

    addKeyReference: function (keyReference) {
        this.keyReferences[this.keyReferences.length] = keyReference;
        for (var i = 0; i < this.keys.length; i++) {
            keyReference.keyChanged(i + 1, this.keys[i]);
        }
    },

    removeKey: function (key) {
        var index = Array.indexOf(this.keys, key);
        Array.remove(this.keys, key);
        for (var i = 0; i < this.keyReferences.length; i++) {
            this.keyReferences[i].keyRemoved(index + 1);
        }
    },

    addKey: function (key) {
        this.keys[this.keys.length] = key;
        for (var i = 0; i < this.keyReferences.length; i++) {
            this.keyReferences[i].keyChanged(this.keys.length, key);
        }
    },

    keyChanged: function (key) {
        var index = Array.indexOf(this.keys, key);
        for (var i = 0; i < this.keyReferences.length; i++) {
            this.keyReferences[i].keyChanged(index + 1, key);
        }
    },

    isKeyUnique: function (key) {
        for (var i = 0; i < this.keys.length; i++) {
            if (this.keys[i] != key && this.keys[i].getDataTypeValue() == key.getDataTypeValue()) return false;
        }
        return true;
    },

    getKeyMax: function () {
        var max = 0;
        for (var i = 0; i < this.keys.length; i++) {
            var current = parseInt(this.keys[i].getDataTypeValue());
            max = (current > max) ? current : max;
        }
        return max;
    },

    getKeys: function () {
        return this.keys;
    }
}


BM.IdentityConstraintBehavior.registerClass('BM.IdentityConstraintBehavior', Sys.UI.Behavior);

// BaseIdentity object

BM.BaseIdentity = function(item, data) {
    BM.BaseIdentity.initializeBase(this, [item, data]);
}

BM.BaseIdentity.prototype = {
    getName: function() {
        return this.getProperty('name');
    },

    getRootPath: function() {
        return this.getProperty('rootPath');
    },

    getRootItem: function() {
        return BM.ItemsNavigator.selectSingle(this.item, this.getRootPath());
    },

    getBehaviorId: function() {
        return this.getRootItem().getId() + '_' + this.getName();
    },

    getBehavior: function() {
        return $find(this.getBehaviorId());
    }
}

BM.BaseIdentity.registerClass("BM.BaseIdentity", BM.Constraint);


// Key object

BM.Key = function(item, data) {
    BM.Key.initializeBase(this, [item, data]);
}

BM.Key.prototype = {
    load: function() {
        BM.Key.callBaseMethod(this, 'load');
        this.getBehavior().addKey(this);
        this.item.getDescriptor().addDescriptionChanged(Function.createDelegate(this, this.raiseDescriptionChange));
        this.item.addChanged(Function.createDelegate(this, this.raiseValueChange));
        this.processAutoFill();
    },

    unload: function() {
        BM.Key.callBaseMethod(this, 'unload');
        this.getBehavior().removeKey(this);
    },

    processAutoFill: function() {
        if (!this.isAutoFill()) return;
        if (this.item.getValue() != '') return;
        this.item.setValue(this.getAutoFillValue());
    },

    getAutoFillValue: function() {
        var autoFillMethod = this.getAutoFillMethod();
        if (autoFillMethod == null) {
            return (this.getBehavior().getKeyMax() + 1).toString();
        }
        return autoFillMethod(this).toString();
    },

    getAutoFillMethod: function() {
        var autoFillMethodName = this.getAutoFillMethodName();
        if (autoFillMethodName == null) {
            return null;
        }
        return eval(autoFillMethodName);
    },

    getAutoFillMethodName: function() {
        if (this.autoFillMethodName == null) {
            this.autoFillMethodName = this.getProperty('autoFillMethodName');
        }
        return this.autoFillMethodName;
    },

    isAutoFill: function() {
        return this.getProperty('autoFill');        
    },

    isMet: function() {
        return this.getBehavior().isKeyUnique(this);
    },

    getDefaultError: function() {
        return BM.Messages['KeyError'];
    },

    getValue: function() {
        return this.item.getValue();
    },

    getDataTypeValue: function() {
        return this.item.getDataTypeValue();
    },

    getDescription: function() {
        return this.item.getDescription();
    },

    raiseValueChange: function() {
        this.getBehavior().keyChanged(this);
    },

    raiseDescriptionChange: function() {
        this.getBehavior().keyChanged(this);
    }
}

BM.Key.registerClass("BM.Key", BM.BaseIdentity);

// KeyReference object

BM.KeyReference = function(item, data) {
    BM.KeyReference.initializeBase(this, [item, data]);
}

BM.KeyReference.prototype = {
    load: function () {
        BM.KeyReference.callBaseMethod(this, 'load');
        this.getBehavior().addKeyReference(this);
    },

    getSelect: function () {
        return this.getItem().getInput();
    },

    keyChanged: function (index, key) {
        var changedOption = this.getSelect().options[index];
        if (changedOption == null) {
            changedOption = new Option();
            this.getSelect().options[index] = changedOption;
        }
        changedOption.value = key.getValue();
        changedOption.text = key.getDescription();
    },

    keyRemoved: function (index) {
        this.getSelect().options[index] = null;
    },

    getCorrespondingKey: function () {
        var index = this.getSelect().selectedIndex - 1;
        if (index < 0) {
            return null;
        }

        return this.getBehavior().getKeys()[index];
    }
}

BM.KeyReference.registerClass("BM.KeyReference", BM.BaseIdentity);